﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ewk.Runtime.Serialization
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
    public abstract class DatarecordAttribute : Attribute
    {
        protected internal abstract IEnumerable<DatafieldAttribute> PrepareDatafieldAttributes(IEnumerable<DatafieldAttribute> datafieldAttributes);

        protected internal abstract string Serialize<T>(T datarecord, IEnumerable<DatafieldAttribute> datafieldAttributes);

        protected internal abstract T Deserialize<T>(string datarecord, IEnumerable<DatafieldAttribute> datafieldAttributes);

        /// <summary>
        /// Occurs when subscribed on and the sum of lengths of records in the datarecord definition
        /// is greater than the length of the datarecord definition.
        /// </summary>
        /// <remarks>
        /// When a client has not subscribed on this event and the situation of DatarecordOverflow occurs,
        /// a <see cref="DatarecordOverflowException"/> is trown.
        /// </remarks>
        internal event EventHandler<DatarecordOverflowEventArgs> DatarecordOverflow;

        protected void OnDatarecordOverflow(object sender, string message)
        {
            if (DatarecordOverflow == null)
            {
                throw new DatarecordOverflowException(message);
            }

            DatarecordOverflow(sender, new DatarecordOverflowEventArgs(message));
        }

        /// <summary>
        /// Occurs when subscribed on and the sum of lengths of records in the datarecord definition
        /// is smaller than the length of the datarecord definition.
        /// </summary>
        /// <remarks>
        /// When a client has not subscribed on this event and the situation of DatarecordIncomplete occurs,
        /// a <see cref="DatarecordIncompleteException"/> is trown.
        /// </remarks>
        internal event EventHandler<DatarecordIncompleteEventArgs> DatarecordIncomplete;

        protected void OnDatarecordIncomplete(object sender, string message)
        {
            if (DatarecordIncomplete == null)
            {
                throw new DatarecordIncompleteException(message);
            }

            DatarecordIncomplete(sender, new DatarecordIncompleteEventArgs(message));
        }
    }
}